import request from '@/utils/request'
import PaginationSelect from '@/class/Pagination/select'
import moment from 'moment'
import _ from 'lodash'

export default class Pagination extends PaginationSelect {
  constructor(scope, url, option = {}) {
    super(scope, option)

    if (!scope) {
      return
    }

    this.scope = scope
    this.__isMore = option.isMore
    this.__isLazy = option.isLazy
    this.doLayout = option.doLayout
    this.option = option

    /**
     * @desc 钩子函数
     */
    this.__search = option.search || null
    this.__reset = option.reset || null
    this.__success = option.success || ''
    this.__fail = option.fail || (res => res)
    this.__before = option.before || (res => res)
    this.__beforeRes = option.beforeRes || (res => res)

    /**
     * @desc 属性
     */
    this.__rowKey = option.rowKey || 'list'
    this.__isFilterStatus = false

    this.setHeight(option)
    this.response = {}
    this.screen = option.screen
    this.defaultSortParams = option.sortParams || {}
    this.sortParams = { ...option.sortParams }
    this._handleAxiosConfig(url)
  }

  /**
   * @desc 参数变量
   */
  sortParams = {};
  queryParams = {};
  alwaysParams = {};
  onceParams = {};

  // 翻页方法
  turn() {
    this.axios()
  }

  /**
   * @desc 处理请求参数
   */
  _handleAxiosConfig(url, data = {}, isAutoAxiosConfig = true) {
    let l1, l2, l3
    const _url = url.split(' ')
    if (_url.length === 2) {
      l1 = _url[0].toUpperCase()
      l2 = _url[1]
    } else if (_url.length === 1) {
      l1 = 'GET'
      l2 = _url[0]
    } else if (_url.length === 3) {
      l1 = _url[0].toUpperCase()
      l2 = _url[1]
      l3 = _url[2]
    }

    if (isAutoAxiosConfig) {
      this.__axiosConfig = {
        method: l1,
        url: l2,
        [l1 === 'GET' ? 'params' : 'data']: data
      }
      return this
    } else {
      const result = {
        method: l1,
        url: l2,
        [l1 === 'GET' ? 'params' : 'data']: data
      }
      if (l3) {
        result['msg'] = l3
      }
      return result
    }
  }

  /**
   * @desc 请求的方法
   */
  axios(
    hooks
  ) {
    hooks = Object.assign(
      {
        success: (res) => {},
        err: () => {}
      },
      hooks
    )

    this.scope[this.keys.table].loading = true
    this._handleParams(true)
    this.__before()
    // this.scope[this.keys.table].data = []
    // 让请求最后执行，为了可以在组件中对过滤项进行初始设值
    request(this.__axiosConfig)
      .then((res) => {
        res = this.__beforeRes(res) || res
        this._handleSuccess(res.data)._setFilterOptionsEd().dealRember()
        if (this.__success) this.__success(res.data)
        res = hooks.success(res) || res
      })
      .catch((err) => {
        console.log(err)
        this.__fail(err)
        hooks.err()
      })
      .finally(() => {
        // setTimeout(() => {
        this.scope[this.keys.table].loading = false
        // }, 100)
      })
  }

  /**
   * @desc 处理请求参数
   * isAutoAxiosConfig 是否自动进行axiosConfig配置
   */
  _handleParams(isAutoAxiosConfig = false) {
    const params = {
      ...this._adaptivePageKey(),
      ...this.sortParams,
      ...this.alwaysParams,
      ...this.queryParams,
      ...(this.__isFilterStatus ? this.scope[this.keys.filter] : {}),
      ...this.onceParams
    }

    // 处理范围类的时间选择器
    if (params['dataRange_type_1']) {
      params.startTime = moment(params['dataRange_type_1'][0]).valueOf() / 1000
      params.endTime = moment(params['dataRange_type_1'][1]).valueOf() / 1000
      delete params['dataRange_type_1']
    }

    // 处理范围类的时间选择器
    if (params['dataRange_type_1_1']) {
      params.startTime = moment(params['dataRange_type_1_1'][0]).format('yyyy-MM-DD 00:00:00')
      params.endTime = moment(params['dataRange_type_1_1'][1]).format('yyyy-MM-DD 23:59:59')
      delete params['dataRange_type_1_1']
    }

    // 处理范围类的时间选择器
    if (params['mouthRange_type_1']) {
      params.startMonth = moment(params['mouthRange_type_1'][0]).format('YYYYMM')
      params.endMonth = moment(params['mouthRange_type_1'][1]).format('YYYYMM')
      delete params['mouthRange_type_1']
    }

    for (const i in params) {
      if (_.endsWith(i, '_type_1000')) {
        if (params[i]) {
          params[i.replace('_type_1000', '')] = params[i] / 1000
        }
      }
      if (_.isArray(params[i])) {
        params[i] = params[i].filter(item => {
          return !['__全选__'].includes(item)
        })
      }
    }

    if (isAutoAxiosConfig) {
      if ('params' in this.__axiosConfig) {
        this.__axiosConfig.params = params
      } else {
        this.__axiosConfig.data = params
      }
    }

    return params
  }

  /**
   * @desc 数据请求成功后的处理函数
   */
  _handleSuccess(res) {
    this.response = res
    // 解决list 为null undefined 会报错的问题
    let list = _.get(res, this.__rowKey, [])
    if (!list) {
      list = []
    }
    this.scope[this.keys.table].isEmpty = list.length < 1
    this.scope[this.keys.table].data = list
    this.pageOption.total = res.count
    this.pageOption.pageSize = res.pageSize
    this.pageOption.pageNo = res.pageIndex
    // if (this.__isLazy) {
    //   this.lazyFun()
    // }
    return this
  }

  /**
   * @desc 懒加载
   */
  lazyFun() {
    if (!this.__isLazy) return
    this.scope.$nextTick(() => {
      // 实现懒加载
      const filterDom = (selector) => {
        const doms = document.querySelectorAll(selector)
        const results = []
        for (let i = 0; i < doms.length; i++) {
          if (doms[i].parentNode.parentNode.parentNode.className.indexOf('el-table__body-wrapper') !== -1) {
            results.push(doms[i])
          }
        }
        return results
      }
      const observerCall = (changes) => {
        changes.forEach((change) => {
          if (change.isIntersecting) {
            const container = change.target
            const parent = container.parentNode
            const index = Array.prototype.indexOf.call(parent.children, container)
            const data = this.scope[this.keys.table].data[index]
            if (data && data.__lazyFun) {
              data.__lazyFun()
            }
            observer.unobserve(container)
          }
        })
      }
      const observer = new IntersectionObserver(observerCall, {})
      filterDom('.el-table__row').forEach((item) => {
        observer.observe(item)
      })
    })
  }

  /**
   * @desc 返回的页码字段适配
   */
  _adaptivePageKey() {
    return {
      pageIndex: this.pageOption.pageNo,
      total: this.pageOption.count,
      pageSize: this.pageOption.pageSize
    }
  }

  /**
   * @desc 对data数据进行筛选
   */
  toScreen(isScreen = false) {
    // 解决list 为null undefined 会报错的问题
    let list = _.get(this.response, this.__rowKey, [])
    if (!list) {
      list = []
    }
    if (isScreen && _.isFunction(this.screen)) {
      this.scope[this.keys.table].data = list.filter(this.screen)
    } else {
      this.scope[this.keys.table].data = list
    }

    this.tableScope.$nextTick(() => {
      this.tableScope.$refs[this.rember.ref].doLayout()
    })
  }

  /**
   * @desc 刷新
   */
  reload(options) {
    this.axios(options)
  }

  /**
   * @desc 自定义搜索函数回调
   */
  _custSearch(options) {
    setTimeout(() => {
      const hooks = Object.assign(
        {
          success: (res) => {},
          err: () => {}
        },
        options
      )
      this.scope[this.keys.table].loading = true
      const param = this._handleParams()
      this.__before()

      this.__search(param, {
        success: (res) => {
          res = this.__beforeRes(res) || res
          this._handleSuccess(res.data)._setFilterOptionsEd().dealRember()
          if (this.__success) this.__success(res.data)
          res = hooks.success(res) || res
          this.scope[this.keys.table].loading = false
        },
        fail: (err) => {
          this.__fail(err)
          hooks.err()
          this.scope[this.keys.table].loading = false
        }
      })
    })
  }

  /**
   * @desc 查询
   */
  search(options) {
    this.pageOption.pageNo = 1
    this.__isFilterStatus = true

    if (this.__search) {
      this._custSearch(options)
    } else {
      setTimeout(() => {
        this.axios(options)
      })
    }
  }

  /**
   * @desc 重置
   */
  reset(options) {
    this.pageOption.pageNo = 1
    this.__isFilterStatus = options.filterStatus || false

    if (options.notClearKeys && options.notClearKeys.length > 0) {
      for (const i in this.scope[this.keys.filter]) {
        if (!options.notClearKeys.includes(i)) {
          this.scope.$delete(this.scope[this.keys.filter], i)
        }
      }
    } else {
      this.scope[this.keys.filter] = {}
    }

    if (this.__search) {
      this._custSearch(options)
    } else {
      setTimeout(() => {
        this.axios({
          err: options.err || (() => {}),
          success: () => {
            options.success ? options.success() : ''
          }
        })
      })
    }
  }

  /**
   * @desc 保存已过滤的参数
   */
  _setFilterOptionsEd() {
    if (this.__isFilterStatus) {
      const filterOptions = this.scope[this.keys.filter]
      const filterOptionsEd = this.scope[this.keys.filterEd]
      for (const i in filterOptions) {
        this.scope.$set(filterOptionsEd, i, filterOptions[i])
      }
    } else {
      this.scope[this.keys.filterEd] = {}
    }
    return this
  }

  /**
   * @desc 获取页码
   */
  getPageSizes() {
    return this.__pageSizes
  }

  /**
   * @desc 处理页码改变
   */
  handleSizeChange(val) {
    this.pageOption.pageNo = 1
    this.pageOption.pageSize = val
    this.axios()
  }

  /**
   * @desc 处理页码改变
   */
  handleCurrentChange(v) {
    const { page, limit, pageSizeChange } = v
    if (pageSizeChange) {
      // 判断是否是改变了页面的pagesize
      this.handleSizeChange(limit)
    } else {
      this.pageOption.pageNo = page
      this.axios()
    }
  }

  /**
   * @desc 操作统一处理逻辑
   */
  operator(config, queryParms) {
    let url, data
    const key = {}
    let isCheck = true
    let isReload = true
    let cancelCb = () => {}
    let okCb = () => {}
    let isHasTip = true

    if (typeof config === 'object') {
      url = config.url
      data = config.data
      if ('isCheck' in config) {
        isCheck = config.isCheck
      }
      if ('isReload' in config) {
        isReload = config.isReload
      }
      if ('isHasTip' in config) {
        isHasTip = config.isHasTip
      }
      if ('cancel' in config) {
        cancelCb = config.cancel
      }
      if ('ok' in config) {
        okCb = config.ok
      }
      config.allKey ? (key.allKey = config.allKey) : ''
      config.mapKey ? (key.mapKey = config.mapKey) : ''
      config.removeAllKey ? (key.removeAllKey = config.removeAllKey) : ''
    } else if (typeof config === 'string') {
      url = config
      data = queryParms
    }

    if (!isCheck) {
      const axiosConfig = this._handleAxiosConfig(url, data, false)
      this._operatorAxios(axiosConfig, cancelCb, okCb, isReload, isHasTip)
      return
    }
    this.checkRember({
      success: (params) => {
        this.scope[this.keys.table].operatorLoad = true
        const axiosConfig = this._handleAxiosConfig(
          url,
          { ...params, ...data },
          false
        )
        this._operatorAxios(axiosConfig, cancelCb, okCb, isReload, isHasTip)
      },
      ...key
    })
  }

  _operatorAxios(axiosConfig, cancelCb, okCb, isReload, isHasTip) {
    request(axiosConfig)
      .then((res) => {
        this.scope[this.keys.table].operatorLoad = false
        if (isHasTip) {
          this.scope.msgSuccess('操作成功！')
        }
        if (isReload) {
          this.clearRember().turn()
        }
        okCb(res)
      })
      .catch((err) => {
        if (err && err.isClickCancelButton) {
          console.log(err)
          cancelCb()
        }
        this.scope[this.keys.table].operatorLoad = false
      })
  }
  /**
   * @desc 获取当前data
   */
  getData() {
    return this.scope[this.keys.table].data
  }

  /**
   * @desc 设置过滤参数
   */
  setFilterParams(params) {
    if (typeof params === 'object') {
      for (const i in params) {
        this.scope.$set(this.scope[this.keys.filter], i, params[i])
      }
    }
    return this
  }

  /**
   * @desc 设置alwaysParams参数
   */
  setAlwaysParams(params) {
    this.alwaysParams = params
    return this
  }

  /**
   * @desc 排序
   */
  sortChange({ column, prop, order }) {
    if (order === null) {
      this.sortParams = this.defaultSortParams
    } else {
      this.sortParams = {
        [prop + 'Order']: order === 'ascending' ? 'asc' : 'desc'
      }
    }
    this.turn()
  }

  /**
   * @desc 获取最大高度
   */
  getMaxHeight() {
    return Pagination._getMaxHeight(...arguments)
  }

  static _getMaxHeight({ ratio = 1, v = 0 } = {}) {
    const h = document.documentElement.clientHeight * ratio + v
    if (h < 200) return 200
    return h
  }

  setHeight(p) {
    const option = {
      ...this.option,
      ...p
    }
    // 46 是双行筛选 减去单行筛选的差值
    const height = option.height || 0
    // if (this.__isMore) {
    //   height = height - 46
    // }
    const { tableHeight, pageSizes } = getListNum(option.pageSize, height, option.rowHeight)

    this.__pageSizes = pageSizes
    this.style = {
      table: {
        height: tableHeight
      }
    }
    this.pageOption = {
      pageNo: 1,
      total: 1,
      pageSize: this.__pageSizes[0]
    }
  }
}

/**
 * 50 nav header高度
 * 65 搜索区的高度
 * 20 内容区的上padding
 * 28 按钮操作区的高度
 * 40 表头的高度
 * 50 页码操作区的高度
 * 20 内容区下padding
 * 40 内容区留白
 */
function getListNum(pageSize, num = 0, rowHeight = 41) {
  const tableHeight = document.documentElement.clientHeight - 50 - 65 - 20 - 28 - 40 - 50 - 20 - 40 + num
  const listNum = parseInt(
    tableHeight / rowHeight
  )
  let param = listNum
  if (param < 5) {
    param = 5
  }
  return {
    pageSizes: [pageSize || param, 20, 30, 50, 100],
    tableHeight
  }
}
